07 Single Page Application e Rotas

Próxima Atividade
  • Sugerir melhoria
Carregando vídeo

Transcrição

Precisamos exibir photo-list.component.html para que a listagem de fotos esteja funcionando bem no navegador. Para complicar um pouquinho, criaremos um novo componente, simplesmente para que haja dois componentes em photos.module.ts. Este componente exibirá um título, e permitirá que saibamos que ora exibiremos a listagem e ora carregaremos a página do formulário para cadastro de novas imagens.

No terminal, pausaremos o command-line interface com "Ctrl + C", e criaremos photo-form dentro da pasta "photos" usando o comando ng generate component photos/photo-form, e com isso ele aparece automaticamente em declarations de photos.module.ts. Salvaremos o arquivo.

Nosso photo-form.component.html terá a frase "photo-form works!" que manteremos para posteriormente verificarmos se tudo funciona como queremos; poderia ser um conteúdo qualquer. Em seguida, utilizaremos o comando ng serve --open e, no Visual Studio, teremos dois componentes com escopo de página, com uma granularidade alta — "photo-list" e "photo-form".

Se verificarmos a nossa aplicação, da maneira em que ela está estruturada, o primeiro componente a ser carregado e que pode ser conferido em index.html é <app-root>. Então não faz sentido incluirmos um selector de "photo-form" ou de "photo-list", já que isso será fixo. Queremos que o componente adequado seja carregado de acordo com o endereço que o usuário digitar.

É neste sentido que entraremos agora na parte de roteamento de uma Single Page Application. Sendo deste tipo, a página index.html se encarrega de exibir tudo o que a aplicação possui, sem carregar outras páginas. Como funciona esta lógica?

Sabemos que, se acessarmos http://localhost:4200/, a index.html será carregada, que por sua vez carregará, por padrão, <app-root>. Se em vez deste endereço usarmos http://localhost:4200/user/flavio, a impressão é de que queremos acessar uma rota do back end. Da mesma forma, http://localhost:4200/p/add parece uma requisição para o back end.

No entanto, não é assim que funciona. Para o Angular identificar o que será a index.html, ela não carregará <app-root>, e sim funcionará como uma grande lacuna, a qual, de acordo com os endereços digitados, fará um "de/para", verificando origem da rota e tomando uma ação adequada com o componente correspondente.

Chamamos esta rota de path, um caminho. Cada caminho da aplicação, do nosso sistema de rotas, estará associado a um componente. É como se o Angular, ao receber certo endereço no navegador, antes deste acessar o back end e tentar fazer uma requisição, intervirá e verificará se a rota é cadastrada por ele.

Se for este o caso, a requisição não irá ao back end, e a rota ficará com o Angular, que carregará o respectivo componente, interceptando a mudança do endereço, e verificando se é uma rota válida, e por fim carregando o respectivo componente. Caso não seja uma rota válida, a requisição segue para o back end.

O componente <app-root> continuará sendo o primeiro a ser carregado pela aplicação, e dentro de "app", criaremos o arquivo app.routing.module.ts, um módulo, sendo necessário importá-lo. Criaremos este arquivo manualmente, digitando seu conteúdo para entendermos melhor seu fundamento. Por ser um módulo, ele terá @NgModule, e uma constante denominada routes ("rotas"), que será um array JavaScript.

Este array terá a configuração de cada rota da nossa aplicação, e será responsável pelo carregando do componente adequado. Cada configuração é feita por meio de um objeto JavaScript no qual indicamos um path, isto é, para user/flavio (por enquanto fixo) carregaremos o component PhotoListComponent e faremos o auto import. A outra rota é para p/add, para o qual será carregado o componente PhotoFormComponent.

Porém, da maneira como está, teremos problemas, pois o Angular espera encontrar um objeto com propriedade Path. A tipagem estática do TypeScript nos ajuda nisso, então indicaremos que routes é do tipo Routes. Porém, ao tentarmos importá-lo, o Angular CLI não nos dará uma sugestão, pois seu módulo de rotas ainda não foi carregado.

Como queremos que ele não seja carregado ainda, o importaremos manualmente:

import { NgModule } from '@angular/core';
import { Routes } from '@angular/router';

import { PhotoListComponent } from './photos/photo-list/photo-list.component';
import { PhotoFormComponent } from './photos/photo-list/photo-form.component';

const routes: Routes = [
    { path: 'user/flavio', component: PhotoListComponent },
    { path: 'p/add', component: PhotoFormComponent }
];

@NgModule({

})
export class AppRoutingModule { }

Ao fazermos isto, o programa entende que cada item do array precisa ser um objeto JavaScript com tais propriedades, e tudo está muito bem tipado. Continuando, em NgModule precisamos importar o RouterModule, que é o módulo de rotas do Angular. Entretanto, deste modo, o AppRoutingModule importa o RouterModule, o qual não está linkado ao arquivo de rotas que acabamos de criar (routes), ou seja, não há uma relação entre eles.

Então, não importaremos RouterModule diretamente em imports, e utilizaremos forRoot(). Sendo nossa aplicação localhost:4200, tudo o que for 4200/ terá relação com a rota raiz. Então, o resultado de forRoot() será importado, e levará em consideração esta lista de rotas (RouterModule).

@NgModule({
    imports: [ RouterModule.forRoot(routes) ]
})

É como se tivéssemos um RouterModule pré-configurado que conhece as rotas da aplicação de antemão, em vez de passarmos um RouterModule que não sabe de nada. Salvaremos o arquivo e acessaremos app.module.ts, e importaremos AppRoutingModule. Com isso, o BrowserModule virá junto, com as rotas pré-configuradas.

Dica: às vezes o Angular CLI fica um pouco perdido quando há importação de um arquivo de módulo de rotas. Então, antes de tudo, é recomendado pausar o terminal do Angular e em seguida rodá-lo novamente.

Abriremos o navegador e consultaremos o console. Não há nenhuma mensagem de erro, então vamos tentar acessar a rota digitando localhost:4200/user/flavio na barra de navegação. Nada acontece, nenhuma requisição ao back end é realizada, e nenhum dado é exibido. Por que?

O primeiro componente a ser carregado pela aplicação é app.component.html, certo? Sendo assim, precisaremos indicar nele que, de acordo com um determinado endereço, o componente correspondente deverá ser carregado, e que isso deve ser exibido neste mesmo arquivo. Para isso, usaremos a diretiva <router-outlet>, deixando o arquivo da seguinte forma:

<router-outlet></router-outlet>

É dentro desta tag que deverá se exibir o componente. Salvaremos, retornaremos ao navegador, e nos depararemos com uma mensagem de erro indicando que <router-outlet> é um elemento desconhecido, e que não é um componente, solicitando a verificação de seu pertencimento a algum módulo.

O que acontece é que AppModule importa AppRoutingModule, bem como os arquivos de configuração de rotas. No entanto, não consegue importar as diretivas de rotas do módulo RouterModule. Para resolvermos isso, poderíamos simplesmente importá-lo em app.module.ts, porém optaremos por uma alternativa: em @NgModule de app.routing.module.ts, exportaremos RouterModule.

@NgModule({
    imports: [
        RouterModule.forRoot(routes)
    ],
    exports: [ RouterModule ]
})

Assim, informamos que quem for importar AppRoutingModule também receberá RouterModule, o que fará com que não haja responsabilidade de importá-lo. Com esta alteração, nada será modificado em app.module.ts, voltaremos ao navegador e acessaremos localhost:4200/user/flavio mais uma vez, e as imagens serão carregadas com sucesso. E se acessarmos localhost:4200/p/add, o outro componente também terá o carregamento bem sucedido.

Tirar dúvida Próxima Atividade
ícone Angular parte 1: Fundamentos

Angular parte 1: Fundamentos

100%
Aula04 de 07

Single Page Applications e rotas

Atividades 7 de 13

  • 01 Projeto da aula anterior
  • 02 Organizando ainda mais nossa aplicação 11min
  • 03 Gerar componente pelo CLI
  • 04 Separar código
  • 05 BrowserModule e CommonModule 05min
  • 06 Sobre módulos
  • 07 Single Page Application e Rotas 15min
  • 08 Lidando com rotas inexistentes 07min
  • 09 Sobre roteamento
  • 10 Segmentos de rotas 06min
  • 11 Qual rota?
  • 12 Consolidando seu conhecimento
  • 13 O que aprendemos?

Aulas

Outros Links

Fórum Trocar Curso
Gravatar de Marcos Katsumi Kay

Marcos Katsumi Kay 34.0k xp

Logo da Alura